package com.ywt.cda.access;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.util.AssertionHolder;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.supply.epp.auth.hessian.service.UserBasicService;
import com.ywt.cda.domain.UserAgent;
import com.ywt.cda.enums.FunctionsEnum;

public class AuthorityHandlerInterceptor extends HandlerInterceptorAdapter
{
	private static final Integer placeholder = Integer.valueOf(0);
	
	private UserBasicService userBasicService;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		if(request.getAttribute("publicFlag")!=null && (boolean)request.getAttribute("publicFlag")){
			return true;
		}
		if(request.getSession().getAttribute(UserAgent.USER_AGENT_IN_REQUEST) == null) {
			AttributePrincipal principal = AssertionHolder.getAssertion().getPrincipal();
			Map<String, Object> userAttr = principal.getAttributes();
			String userType = userAttr.get("userType").toString();
			String name = principal.getName();
			String appId = userAttr.get("appId").toString();
			List<String> permissionCodes = userBasicService.getPermisionCodes(appId, name);
			UserAgent userAgent = new UserAgent();
			userAgent.riseUp(appId, name, userType, permissionCodes);
			request.getSession().setAttribute(UserAgent.USER_AGENT_IN_REQUEST, userAgent);
		}

		UserAgent userAgent = (UserAgent) request.getSession().getAttribute(UserAgent.USER_AGENT_IN_REQUEST);
		request.setAttribute(UserAgent.USER_AGENT_IN_REQUEST, userAgent);
		if (!pass(userAgent, handler)) {
			throw new AccessDeniedException();
			// 到异常控制类中去处理
		}
		return true;
	}

	private Map<Method, FunctionsEnum[]> caches = new ConcurrentHashMap<Method, FunctionsEnum[]>();

	private Map<Method, Integer> noControlCaches = new ConcurrentHashMap<Method, Integer>();// 没有配置AdminAccess的method

	private boolean pass(UserAgent userAgent, Object handler) {
		FunctionsEnum[] funs = null;
		HandlerMethod handlerMethod = (HandlerMethod) handler;
		funs = this.caches.get(handlerMethod.getMethod());
		if (funs == null) {
			if (noControlCaches.containsKey(handlerMethod.getMethod())) {
				// 没有UserAgent 配置，允许任意访问
				return true;
			}
			Access access = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Access.class);
			if (access == null) {
				// 没有配置UserAgent
				noControlCaches.put(handlerMethod.getMethod(), placeholder);
				return true;
			}
			funs = access.value();
			this.caches.put(handlerMethod.getMethod(), funs);
		}
		if (funs.length == 0) {
			// 如果配置了缺省的UserAgent,表示只要登录就能访问
			return userAgent.getAppId() != null && userAgent.getLoginName() != null;
		}
		// 配置了UserAgent
		if (userAgent != null) {
			for (FunctionsEnum em : funs) {
				if (userAgent.haveFunction(em)) {
					return true;
				}
			}
		}
		return false;
	}

	public UserBasicService getUserBasicService() {
		return userBasicService;
	}

	public void setUserBasicService(UserBasicService userBasicService) {
		this.userBasicService = userBasicService;
	}
}
